<?php
/**
 * Created by PhpStorm.
 * User: Jan-Home
 * Date: 2018/4/5 0005
 * Time: 14:42
 */

namespace Gitee\Cache;

use Ke\Adm\CacheModelTrait;
use Ke\Adm\Model;
use Ke\Adm\Query;

class DataIndexCache
{
	
	
	use CacheModelTrait;
	
	// 对象缓存的周期，缓存一天
	protected static $cacheTTL = 60 * 60 * 24;
	
	protected static $version = '0.0.1';
	
	/** @var DataIndexModelImpl */
	protected $model = '';
	
	protected $index = false;
	
	protected $fields = [];
	
	public static function makeCacheKey(): string
	{
		$args = [static::makeCacheBaseKey(...func_get_args())];
		$prefix = 'FieldsIndex';
		if (!empty($prefix))
			array_unshift($args, $prefix);
		$suffix = static::getCacheKeySuffix();
		if (!empty($suffix))
			$args[] = $suffix;
		$spr = static::getCacheKeySeparator();
		return implode($spr, $args);
	}
	
	public function makeCacheHash(): string
	{
		$hash = $this->model;
		$hash .= PHP_EOL . implode('-', $this->fields);
		if ($this->verifyModel($this->model)) {
			$hash .= $this->model::getIndexVersion();
		}
		return hash('md5', $hash);
	}
	
	public function isValidCache()
	{
		if (!$this->verifyModel($this->model) || $this->index === false || empty($this->fields))
			return false;
		return true;
	}
	
	protected function onPrepareCache(string $key, array $args)
	{
		$this->model = $args[0];
		if ($this->verifyModel($this->model)) {
			$this->fields = $this->model::getIndexFields();
			$this->updateAll();
		}
	}
	
	public function verifyModel(string $model)
	{
		if (!empty($model) && class_exists($model) &&
			is_subclass_of($model, Model::class) &&
			is_subclass_of($model, DataIndexModelImpl::class)) {
			return true;
		}
		return false;
	}
	
	private function mkFieldKey($field, $value)
	{
		if (empty($value))
			return null;
		return $field . '_' . $value;
	}
	
	public function updateAll($isSave = false)
	{
		$this->index = [];
		$query = new Query();
		$query->setModel($this->model);
		$all = $query->find();
		foreach ($all as $item) {
			$this->updateItem($item, $isSave);
		}
		if ($isSave) {
			$this->saveCache();
		}
		return $this;
	}
	
	public function updateItem(Model $obj, $isSave = false)
	{
		if ($obj->isExists()) {
			if ($this->index === false)
				$this->index = [];
			$this->removeItemOriginal($obj);
			$pk = $obj->getPk();
			foreach ($this->fields as $field) {
				$key = $this->mkFieldKey($field, $obj[$field]);
				if (!empty($key))
					$this->index[$key] = $pk;
			}
			if ($isSave) {
				$this->saveCache();
			}
		}
		return $this;
	}
	
	protected function removeItemOriginal(DataIndexModelImpl $obj)
	{
		$isUpdate = 0;
		$data = $obj->getOriginalData();
		if (!empty($data)) {
			foreach ($this->fields as $field) {
				$value = $data[$field] ?? '';
				if (!empty($value)) {
					$key = $this->mkFieldKey($field, $value);
					if (isset($this->index[$key])) {
						unset($this->index[$key]); // 删除掉旧的token
						$isUpdate++;
					}
				}
			}
			$obj->clearOriginalData(); // 清空原始数据
		}
		return $isUpdate > 0;
	}
	
	public function destroyItem(Model $obj, $isSave = false)
	{
		if ($this->removeItemOriginal($obj)) {
			if ($isSave) {
				$this->saveCache();
			}
		}
		return $this;
	}
	
	public function getIndexData(string $field, string $value)
	{
		$key = $this->mkFieldKey($field, $value);
		if (!empty($key)) {
			return $this->index[$key] ?? null;
		}
		return null;
	}
}